#include "mycallback.h"

MyCallback::MyCallback(GLWidget *glwidget_, QObject *parent) :
    Sbs2Callback(parent), glwidget(glwidget_)
{



    verticesData = new DTU::DtuArray2D<double>(64,1028);
    colorData = new DTU::DtuArray2D<double>(1028,4); //rgba values

    (*colorData) = 0;

    QObject::connect(sbs2DataHandler,SIGNAL(sourceReconstructionPowerReady()),this,SLOT(soureReconstructionPowerReady()));
    QObject::connect(glwidget,SIGNAL(turnSourceReconstructionPowerOn(int,int,int,int, QString)),this,SLOT(turnSourceReconstructionPowerOn(int,int,int,int, QString)));
    QObject::connect(glwidget,SIGNAL(changeBand(QString)),this,SLOT(changeBand(QString)));


    qsrand(QDateTime::currentMSecsSinceEpoch());
    updateColorMap(3);


    /* This is optional. Remove to work on all brain or add additional regions. */
    //dtuEmotivRegion = new DtuEmotivRegion();
    //dtuEmotivRegion->addRegion("Frontal_Lobe");


#ifdef Q_WS_MAEMO_5
    meanWindowLength = 16;
#else
    meanWindowLength = 32;
#endif
    maxValues = new QVector<double>();
    minValues = new QVector<double>();

    changeBand("alpha");

}

void MyCallback::changeBand(QString name)
{
    minValues->clear();
    maxValues->clear();
    if (name.compare("delta"))
    {
	lowFreq = 1;
	highFreq = 4;
    }
    if (name.compare("theta"))
    {
	lowFreq = 4;
	highFreq = 8;
    }
    if (name.compare("alpha"))
    {
	lowFreq = 8;
	highFreq = 12;
    }
    if (name.compare("lowBeta"))
    {
	lowFreq = 12;
	highFreq = 16;
    }
    if (name.compare("beta"))
    {
	lowFreq = 16;
	highFreq = 20;
    }
}


void MyCallback::getData(Sbs2Packet *packet)
{
    thisPacket = packet;
    currentPacketCounter = packet->counter;
    currentPacket += 1;



    glwidget->updateGyroX(packet->gyroX);
    glwidget->updateGyroY(packet->gyroY);

    sbs2DataHandler->setThisPacket(thisPacket);
    sbs2DataHandler->sourceReconstructionPower();
}


void MyCallback::soureReconstructionPowerReady()
{
    createColorMatrix(sbs2DataHandler->getSourceReconstructionPowerValues());
    updateModel();

}


/**
  This function sees 64x1028 input matrix and should produce 1028x3 color matrix ready to pass to visualization.
  */


void MyCallback::createColorMatrix(DTU::DtuArray2D<double> *verticesData_)
{
    double meanMax = 0;
    double meanMin = 0;


    for (int t=0; t<minValues->size(); ++t)
    {
        meanMin += minValues->at(t);
    }
    if (minValues->size())
        meanMin /= (double)minValues->size();
    for (int t=0; t<maxValues->size(); ++t)
    {
        meanMax += maxValues->at(t);
    }
    if (maxValues->size())
        meanMax /= (double)maxValues->size();

    double currentMax = -999999999;
    double currentMin = 9999999999;

    double scaling = meanMax - meanMin;

    for (int vertex = 0; vertex<verticesData_->dim2(); ++vertex)
    {
        double this_vertex_power = 0.0;
        for (int freq = lowFreq; freq < highFreq; ++freq)
        {
            this_vertex_power += (*verticesData_)[freq][vertex];

        }
            this_vertex_power = 20 * qLn(this_vertex_power + 1)/qLn(10);
            if (this_vertex_power > currentMax) currentMax = this_vertex_power;
            if (this_vertex_power < currentMin) currentMin = this_vertex_power;

            double v = 0.0;


            v += (this_vertex_power - meanMin)/scaling * 1.0;
            if (v < 0.5) v = 0;
            if (v > 1.0) v = 1.0;


            (*colorData)[vertex][0] = 1.0 - v;
            (*colorData)[vertex][1] = 1.0 - v;
            (*colorData)[vertex][2] = 1.0;
            (*colorData)[vertex][3] = 1.0;



    }


    minValues->append(currentMin);
    if (minValues->size() == meanWindowLength) minValues->erase(minValues->begin());
    maxValues->append(currentMax);
    if (maxValues->size() == meanWindowLength) maxValues->erase(maxValues->begin());



}


//void MyEmotivCallback::createColorMatrix(DTU::DtuArray2D<double>* verticesData_)
//{



//    /*
//    This uses moving average over meanWindowLength time bins.
//    Standard frequency of 3D reconstruction we use is 8Hz, so setting meanWindowLength = 32 equals to 4 second average.
//    For Maemo we set frequency of 3D reconstruction to 4Hz due to insufficient processing power and set meanWindowLength = 16
//    The mean is calculated over sum of powers in the band for all vertices.
//    Each vertex is colored red if it is above average (taken from the last time bin to do everything in one iteration.
//    If vertex power is below average, it will stay gray. If it is 2 times the average, it will be fully red. Linearly red in between.
//      */

//    meanPower = 0.0;
//    for (int t=0; t<meanValues->size(); ++t)
//    {
//	meanPower += meanValues->at(t);
//    }
//    if (meanValues->size())
//	meanPower /= (double)meanValues->size();


//    double sum_power = 0;
//    for (int vertex = 0; vertex < verticesData_->dim2(); ++vertex)
//    {
//	double this_vertex_power = 0.0;
//	for (int freq = lowFreq; freq < highFreq; ++freq)
//	{
//	    this_vertex_power += (*verticesData_)[freq][vertex];

//	}

//	//Color lookup
//	/*
//	double v = int(( (std::min(std::max(this_vertex_power/((double)meanPower + 0.0001),1.0),2.0)-1.0)) * 255);
//	(*colorData)[vertex][0] = cmap.at( v * 3);
//	(*colorData)[vertex][1] = cmap.at( v * 3 + 1);
//	(*colorData)[vertex][2] = cmap.at( v * 3 + 2);
//	*/
//	/*
//	(*colorData)[vertex][0] = 0.5 + (std::min(std::max(this_vertex_power/((double)meanPower + 0.0001),1.0),2.0)-1.0) * 0.5;
//	(*colorData)[vertex][1] = 0.5;
//	(*colorData)[vertex][2] = 0.5;
//	*/

//	/* rainbow brain
//	int chooser = qrand()%3;
//	(*colorData)[vertex][0] = 0.5;
//	(*colorData)[vertex][1] = 0.5;
//	(*colorData)[vertex][2] = 0.5;

//	(*colorData)[vertex][chooser] = 0.5 + (std::min(std::max(this_vertex_power/((double)meanPower + 0.0001),1.0),2.0)-1.0) * 0.5;
//	*/

//	(*colorData)[vertex][0] = 0.5;
//	(*colorData)[vertex][1] = 0.5;
//	(*colorData)[vertex][2] = 0.5 + (std::min(std::max(this_vertex_power/((double)meanPower + 0.0001),1.0),2.0)-1.0) * 0.5;



//	(*colorData)[vertex][3] = 1.0;
//	sum_power += this_vertex_power;

//    }


//    if (dtuEmotivRegion != 0)
//	meanValues->append(sum_power/dtuEmotivRegion->getVerticesToExtract()->size());
//    else
//	meanValues->append(sum_power/colorData->dim1());
//    if (meanValues->size() == meanWindowLength) meanValues->erase(meanValues->begin());



//}

void MyCallback::updateModel()
{


    for (int vertex = 0; vertex < colorData->dim1(); ++vertex)
    {
        glwidget->updateColorForVertex(vertex,(*colorData)[vertex][0],(*colorData)[vertex][1],(*colorData)[vertex][2], (*colorData)[vertex][3]);

    }

}

void MyCallback::updateColorMap(int colorMap)
{

    qDebug() << "updating color map "<<colorMap;

    QString filename(":/colortable");
    filename.append(QString::number(colorMap));

    QFile file2(filename);

    if (!file2.open(QIODevice::ReadOnly | QIODevice::Text))
        qDebug() <<"file problem";

    int i=0;
    cmap.clear();
    while (!file2.atEnd())
    {
        QByteArray line = file2.readLine();
        QString str = line.data();
        QStringList list1 = str.split(",");
        for (int j = 0; j < list1.size(); j++)
        {
            cmap.push_back(list1.at(j).toDouble());
        }
        i++;

    }

}

